This document present tests on divergence and curl module calculation using pygsf.
The modules to import for dealing with grids are:
In [1]:
from pygsf.mathematics.arrays import *
In [2]:
from pygsf.spatial.rasters.geotransform import *
In [3]:
from pygsf.spatial.rasters.fields import *
The definition of divergence for our 2D case is:
The definition of curl module in our 2D case is:
so that the module of the curl is:
The implementation of the curl module calculation has been debugged using the code at [2] by Johnny Lin. Deviations from the expected theoretical values are the same for both implementations.
We calculate a theoretical, 2D vector field and check that the parameters calculated by pygsf is equal to the expected one.
We use a modified example from p. 67 in [3].
In order to create the two grids that represent the x- and the y-components, we therefore define the following two "transfer" functions from coordinates to z values:
In [4]:
def z_func_fx(x, y):
return 0.0001 * x * y**3
def z_func_fy(x, y):
return - 0.0002 * x**2 * y
The above functions define the value of the cells, using the given x and y geographic coordinates.
Gridded field values are calculated for the theoretical source vector field x- and y- components using the provided number of rows and columns for the grid:
In [5]:
rows=100; cols=200
In [6]:
size_x = 10; size_y = 10
In [7]:
tlx = 500.0; tly = 250.0
Arrays components are defined in terms of indices i and j, so to transform array indices to geographical coordinates we use a geotransform. The one chosen is:
In [8]:
gt1 = GeoTransform(
inTopLeftX=tlx,
inTopLeftY=tly,
inPixWidth=size_x,
inPixHeight=size_y)
Note that the chosen geotransform has no axis rotation, as is in the most part of cases with geographic grids.
In [9]:
fx1 = array_from_function(
row_num=rows,
col_num=cols,
geotransform=gt1,
z_transfer_func=z_func_fx)
In [10]:
fy1 = array_from_function(
row_num=rows,
col_num=cols,
geotransform=gt1,
z_transfer_func=z_func_fy)
the theoretical divergence transfer function is:
In [11]:
def z_func_div(x, y):
return 0.0001 * y**3 - 0.0002 * x**2
The theoretical divergence field can be created using the function expressing the analytical derivatives z_func_div:
In [12]:
theor_div = array_from_function(
row_num=rows,
col_num=cols,
geotransform=gt1,
z_transfer_func=z_func_div)
Divergence as resulting from pygsf calculation:
In [13]:
div = divergence(
fld_x=fx1,
fld_y=fy1,
cell_size_x=size_x,
cell_size_y=size_y)
We check whether the theoretical and the estimated divergence fields are close:
In [14]:
assert np.allclose(theor_div, div)
We test another theoretical, 2D vector field, maintaining the same geotransform and other grid parameters as in the previous example. We use the field described in example 1 in [4]:
The "transfer" functions from coordinates to z values are:
In [15]:
def z_func_fx(x, y):
return y
def z_func_fy(x, y):
return - x
Gridded field values are calculated for the theoretical source vector field x- and y- components using the provided number of rows and columns for the grid:
In [16]:
rows=200; cols=200
In [17]:
size_x = 10; size_y = 10
In [18]:
tlx = -1000.0; tly = 1000.0
Arrays components are defined in terms of indices i and j, so to transform array indices to geographical coordinates we use a geotransform. The one chosen is:
In [19]:
gt1 = GeoTransform(
inTopLeftX=tlx,
inTopLeftY=tly,
inPixWidth=size_x,
inPixHeight=size_y)
Note that the chosen geotransform has no axis rotation, as is in the most part of cases with geographic grids.
In [20]:
fx2 = array_from_function(
row_num=rows,
col_num=cols,
geotransform=gt1,
z_transfer_func=z_func_fx)
In [21]:
fy2 = array_from_function(
row_num=rows,
col_num=cols,
geotransform=gt1,
z_transfer_func=z_func_fy)
The theoretical curl module is a constant value:
The module of curl as resulting from pygsf calculation is:
In [22]:
curl_mod = curl_module(
fld_x=fx2,
fld_y=fy2,
cell_size_x=size_x,
cell_size_y=size_y)
We check whether the theoretical and the estimated curl module fields are close:
In [23]:
assert np.allclose(-2.0, curl_mod)